<template>
    <div class="organize_wrap">
        <div class="tool_bar">
            <n-button @click="handleEvent('add')" strong secondary type="primary" size="small">
                新增节点
            </n-button>
            <n-button @click="handleEvent('remove')" strong secondary type="error" size="small">
                删除节点
            </n-button>
        </div>
        <svg ref="svgRef" :width="svg.width" :height="svg.height" preserveAspectRatio="xMidYMid meet" @wheel="onWheel"
            @mousedown.stop="onMousedown" @mouseup.stop="onMouseup" @mousemove.stop="onMousemove">
            <g :transform="`scale(${scaleLevel}) translate(${movePo.x}, ${movePo.y})`" ref="zoomGroupRef">
                <g v-for="(item, index) in newTreeData" :key="index">
                    <foreignObject :x="item.x" :y="item.y" :width="item.node.width" :height="item.node.height"
                        :fill="config.background" requiredExtensions="http://www.w3.org/1999/xhtml"
                        class="foreign-bject">
                        <div :class="['node', { 'is_active': item.isActive }]" 
                            @click.stop="selecteNode(item, index)"
                            @mousemove.stop="onNodeMousemove"
                            :style="{ color: config.textColor, background: config.background }">
                            <section class="head">
                                <p class="image"><img src="./assets/common.png" alt="" srcset=""></p>
                                <span>{{ item.node.label }}</span>
                            </section>
                            <section>{{ item.node.position }}</section>
                        </div>
                    </foreignObject>
                </g>
                <g v-for="(item, index) in edgesData" :key="index">
                    <path :d="`M${item.points[0].x},${item.points[0].y} 
                    C${item.points[2].x},${item.points[2].y} ${item.points[3].x},${item.points[3].y} 
                    ${item.points[1].x},${item.points[1].y}`" :stroke="config.stroke" stroke-width="2" fill="none" />
                </g>
            </g>
        </svg>
    </div>
</template>

<script setup>
import { nextTick } from 'vue';
import CarrotTree from './core/CarrotTree';
import { nodes } from './treeData';
import { initCofing } from './core/config';
import Node from "./core/Node";
import { useNaiveDiscrete } from "@/hooks/navie-ui";

var carrotTree;
const { message } = useNaiveDiscrete()
const config = ref({ ...initCofing.color })
const svgRef = ref(null)
const newTreeData = ref([...nodes])
const edgesData = ref([])
const svg = reactive({
    width: 1100,
    height: 650,
    nodes
});

// 选中节点
const selectOne = ref(null)
const selecteNode = (node_, index_) => {
    carrotTree.selectOne(node_, index_)
}

// 操作节点
const handleEvent = (type) => {
    if (!selectOne.value) {
        message.info('请选中节点在操作')
        return
    }

    if (type === 'add') {
        const node = new Node({
            label: `子节点${Math.round(Math.random(1000)*100)}`,
            id: `Node_${new Date().getTime()}${new Date().getMilliseconds()}`
        })
        const newList = carrotTree.add(selectOne.value, node)
        newTreeData.value = JSON.parse(JSON.stringify(newList))
    }
    if (type === 'remove') {
        if (selectOne.value.id === 'root') {
            message.warning('根元素不能删除')
            return
        }
        const newList1 = carrotTree.remove(selectOne.value)
        newTreeData.value = JSON.parse(JSON.stringify(newList1))
    }
}

// 滚动事件
const zoomGroupRef = ref(null)
const scaleLevel = ref(1)
let couter = 1
const onWheel = (evt) => {
    // 阻止默认的滚轮行为
    evt.preventDefault();
    const svgWidth = svgRef.value.clientWidth;
    const svgHeight = svgRef.value.clientHeight;
    const centerX = svgWidth / 2;
    const centerY = svgHeight / 2;
    zoomGroupRef.value.setAttribute('transform-origin', `${centerX} ${centerY}`);
    // deltaY 大于0向后滚，小于0向前滚
    if (evt.deltaY < 0 && scaleLevel.value > 0.1) {
        couter -= 0.1
    } else {
        couter += 0.1
    }
    scaleLevel.value = parseFloat(couter.toFixed(1))
}

// 拖拽事件
const isDowning = ref(false)
const movePo = reactive({
    x: 0,
    y: 0
})
const startPo = ref({
    x: 0,
    y: 0
})
const onMousedown = evt => {
    evt.preventDefault()
    isDowning.value = true
    startPo.value.x = evt.offsetX - movePo.x
    startPo.value.y = evt.offsetY - movePo.y
}
const onMouseup = evt => {
    evt.preventDefault()
    isDowning.value = false
}
const onMousemove = evt => {
    evt.preventDefault()
    if (isDowning.value) {
        movePo.x = evt.offsetX - startPo.value.x
        movePo.y = evt.offsetY - startPo.value.y
    }
}

const onNodeMousemove = evt => {
    evt.preventDefault()
    isDowning.value = false
}

// 监听内部数据变化
const listenerSelect = (data) => {
    const { nodes, active } = data
    selectOne.value = active
    newTreeData.value = [...nodes]
}

onMounted(() => {
    carrotTree = new CarrotTree({
        el: svgRef.value,
        rankdir: 'TB'
    })
    const result = carrotTree.layout(newTreeData.value)
    newTreeData.value = [...result]
    // edgesData.value = carrotTree.getEdgePoints()
    // edgesData.value = carrotTree.getEdges()
    // console.log(edgesData.value, 4878);

    // 监听选择数据变化
    carrotTree.on('selection:updated', listenerSelect)
})

onBeforeUnmount(() => {
    carrotTree.off('selection:updated', listenerSelect)  
})
</script>

<style lang="scss" src="./style.scss"></style>
